import os
import sys
from typing import Dict, Any, Optional
import json
import asyncio

from langchain_core.messages import HumanMessage, AIMessage
from langgraph.constants import END
from langgraph.graph import add_messages

from app.utils.llm_client import LLMClient
from app.models import SessionState, CustomEncoder

# 将项目根目录添加到系统路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from app.utils.logger_util import  user_logger


class ClearOrNot:
    CLEAR = "clear"
    NOT_CLEAR = "not_clear"

message_str='''{
	"type": "",
	"message": 
		{
			"desc": "",
			"data": ""	
		}
    }'''
# 节点函数
def require_clear_or_not_node(state: SessionState,config:dict) -> SessionState:
    """需求明确性检查节点 - 分析用户需求是否完整明确"""

    new_state = state.copy()
    # print("======"+config.get("configurable",{}).get("thread_id"))
    thread_id=config.get("configurable",{}).get("thread_id")
     # 将JSON字符串转换为Python字典


    message_dict = json.loads(message_str)
    message_dict["type"] = "节点"
    message_dict["message"]["desc"] = "需求信息澄清"
    filtered_state = {
        key: value for key, value in new_state.items()
        if key not in ['field_availability','messages','require_json']
    }
    message_dict["message"]["data"] = "*用户需求澄清：" + str(filtered_state)
    #message_dict["message"]["data"] = json.dumps(state,  cls=CustomEncoder,ensure_ascii=False)
    user_logger.info(thread_id, json.dumps(message_dict, ensure_ascii=False))


    # 从反转的消息列表中筛选用户消息，取第一个（即最新的用户消息），如果没有用户消息则为None
    user_input = next((msg.content for msg in reversed(new_state["messages"]) if isinstance(msg, HumanMessage)), None)

    new_state['user_require'].append(user_input)
    joined_user_input = ', '.join(new_state['user_require'])
    #添加sleep()
    message_dict["type"]="操作"
    message_dict["message"]["desc"]="记忆加载，获取用户历史所有输入"
    # data_to_dump = {
    #     'data_struct': joined_user_input  # 添加新字段
    # }
    if new_state['require_json'] is None or new_state['require_json'] == '':
        message_dict["message"]["data"]="*记忆加载,用户历史输入："+str(new_state['messages'])
    else:
        message_dict["message"]["data"]="*记忆加载,用户历史输入："+str(new_state['require_json'])
    user_logger.info(thread_id, json.dumps(message_dict, ensure_ascii=False))

    # 没有用户输入，直接结束
    if user_input is None:
        new_state["messages"] = add_messages(state["messages"], [AIMessage(content="未找到需求输入，对话结束。")])
        new_state["next"] = END
        return new_state

    try:
        # 调用需求明确性分析
        # 传入带 thread_id 的 LLMClient，以便捕获并记录模型的思考内容
        llm = LLMClient(thread_id=thread_id)
        analysis_result = require_clear_or_not(joined_user_input, llm_client=llm)

        # 生成并记录思考摘要
        try:
            think_pack = llm.generate_think_sync(
                purpose="需求明确性判断与要素提取",
                context={
                    "all_user_inputs": joined_user_input,
                    "result": analysis_result,
                },
                max_tokens=300,
            )
            think_text = think_pack.get("display") if isinstance(think_pack, dict) else str(think_pack)
        except Exception:
            think_text = None
        message_dict["type"] = "思考"
        message_dict["message"]["desc"] = think_text or "需求明确性摘要生成失败"
        message_dict["message"]["data"] = "当前判断结果和提取结构已落库"
        user_logger.info(thread_id, json.dumps(message_dict, ensure_ascii=False))
        clearness = analysis_result["clearness"]
        extracted_json = analysis_result.get("extracted_json")

        #missing_fields这个可以从state里面去取

        missing_fields = analysis_result.get("missing_fields", {})

        # 更新状态
        new_state["require_clearness"] = clearness
        if extracted_json:
            new_state["require_json"] = json.dumps(extracted_json, ensure_ascii=False)

        if clearness == ClearOrNot.CLEAR:
            #user_logger.info(thread_id,"当前阶段为需求澄清阶段，需求已经澄清完成，当前需求可分析出来的需求为：" +str( new_state["require_json"]))
            message_dict["type"]="操作"
            message_dict["message"]["desc"]="检查需求完整度"

            # data_to_dump = {
            #  'data_struct': "未发现缺失信息,将继续进行字段级分析"  # 添加新字段
            # }

            message_dict["message"]["data"]="*未发现缺失信息,将继续进行字段级分析"
            user_logger.info(thread_id, json.dumps(message_dict, ensure_ascii=False))
            new_state["messages"] = add_messages(state["messages"], [AIMessage(content="您的需求描述很完整，我已经完成了需求分析。具体解析的各项值如下：" +json.dumps(extracted_json, ensure_ascii=False) )])
            new_state["next"] = "field_availability_check"
        else:
            # 生成澄清问题
            message_dict["type"]="操作"
            message_dict["message"]["desc"]="检查需求完整度"

            data_to_dump = {
             'data_struct': "发现缺失信息:"+str(missing_fields) # 添加新字段
            }
            #message_dict["message"]["data"]=json.dumps(data_to_dump,ensure_ascii=False)
            message_dict["message"]["data"]="*发现缺失信息:"+str(missing_fields)
            user_logger.info(thread_id, json.dumps(message_dict, ensure_ascii=False))
            clarification_question = _generate_clarification_question(missing_fields)

            message_dict["type"]="用户"
            message_dict["message"]["desc"]="用户输入提示"

            data_to_dump = {
             'data_struct':  clarification_question# 添加新字段
            }

            message_dict["message"]["data"]=json.dumps(data_to_dump,ensure_ascii=False)
            user_logger.info(thread_id, json.dumps(message_dict, ensure_ascii=False))

            new_state["messages"] = add_messages(state["messages"], [AIMessage(content=clarification_question)])
            new_state["missing_fields"] = missing_fields
            new_state["next"] = "human_clarify_requirement"

            #在这里打印日志，提示需要用户输入信息
    except Exception as e:
        print(f"需求分析出错: {e}")
        new_state["messages"] = add_messages(state["messages"], [AIMessage(content="需求分析过程中出现错误，对话结束。")])
        new_state["next"] = END

    return new_state


def require_clear_or_not(user_input: str, llm_client: Optional[LLMClient] = None) -> Dict[str, Any]:
    """
    判断用户输入的需求是否明确
    Args:
        user_input: 用户输入的原始文本
        llm_client: 大模型客户端实例

    Returns:
        Dict: 包含clearness结果和extracted_json的字典
    """

    # 如果没有提供llm_client，创建默认实例
    if llm_client is None:
        llm_client = LLMClient()

    # 构建提示词
    system_prompt = """
你是一个数据需求分析专家。请从用户的描述中提取以下JSON结构的信息：

{
    "original_text": "用户的原始需求文本",
    "parsed_require": {
        "data_range": "数据范围",
        "statistical": "统计主体",
        "cycle": "数据周期，[Y M D H W]中的一个",
        "extract_methord": "抽取方式，[增量、全量、新增]中的一个",
        "effectiveness": "时效性，如T+1，M+1等，表示数据更新的时效性",
        "data_source": "数据源端，非必填",
        "applications": "应用场景",
        "sensitive_type": "是否涉及敏感五元组true/false",
        "sensitive_details": "从姓名、证件号、手机号、住址、IMEI中的一个或多个，敏感五元组类型",
        "fields_info": [{
            "original_field": "需求文本中提取的原始字段",
            "field_examples": "数据样例，非必填",
            "direct_from_table": "明确的表名和字段名，非必填"
            "status": "字段状态，非必填，默认值为'1'，表示用户仍需要该字段，'0'表示不需要该字段"
        }]
    }
}
其中sensitive_type的值默认是false,真实取值请你进行推断，如果用户的需求包含姓名、证件号、手机号、住址、IMEI中的一个或多个，则将sensitive_type置为true,否则则置为false
如果判断sensitive_type为true，则需要提取出姓名、证件号、手机号、住址、IMEI，并赋值给sensitive_details
请严格按照上述JSON格式返回结果。如果某个信息无法从用户描述中确定，请填写"未明确"。
除了标注为"非必填"的字段外，其他字段都必须尝试提取。
"""

    user_prompt = f"请分析以下用户需求并提取信息：\n\n{user_input}"
    try:
        # 同步调用异步函数
        extracted_json = asyncio.run(_extract_requirement_json(llm_client, system_prompt, user_prompt))

        # 判断需求是否明确
        clearness_result = _judge_requirement_clearness(extracted_json)

        return {
            "clearness": clearness_result["clearness"],
            "extracted_json": extracted_json,
            "missing_fields": clearness_result.get("missing_fields", {})
        }
    except Exception as e:
        print(f"分析需求时发生错误: {e}")
        return {
            "clearness": ClearOrNot.NOT_CLEAR,
            "extracted_json": None,
            "error": str(e)
        }

async def _extract_requirement_json(llm_client: LLMClient, system_prompt: str, user_prompt: str) -> Dict[str, Any]:
    """
    调用大模型提取需求JSON
    """
    try:
        response = await llm_client.simple_chat(user_prompt, system_prompt)

        # 尝试解析JSON响应
        # 大模型可能返回带有解释的文本，需要提取JSON部分
        response_text = response.strip()

        # 查找JSON部分
        start_idx = response_text.find('{')
        end_idx = response_text.rfind('}') + 1

        if start_idx != -1 and end_idx != 0:
            json_text = response_text[start_idx:end_idx]
            extracted_json = json.loads(json_text)
            return extracted_json
        else:
            # 如果无法找到JSON格式，返回空结构
            return _get_empty_require_json()

    except json.JSONDecodeError:
        print("大模型返回的不是有效的JSON格式")
        return _get_empty_require_json()
    except Exception as e:
        print(f"提取需求JSON时发生错误: {e}")
        return _get_empty_require_json()

def _get_empty_require_json() -> Dict[str, Any]:
    """
    获取空的需求JSON结构
    """
    return {
        "original_text": "",
        "parsed_require": {
            "data_range": "未明确",
            "statistical": "未明确",
            "cycle": "未明确",
            "extract_methord": "未明确",
            "effectiveness": "未明确",
            "data_source": "",
            "applications": "未明确",
            "sensitive_type": "未明确",
            "sensitive_details": "未明确",
            "fields_info": []
        }
    }

def _judge_requirement_clearness(extracted_json: Dict[str, Any]) -> Dict[str, Any]:
    """
    判断需求是否明确，并返回缺失字段信息
    Args:
        extracted_json: 提取的需求JSON
    Returns:
        Dict: 包含clearness状态和missing_fields的字典
    """

    if not extracted_json or "parsed_require" not in extracted_json:
        return {
            "clearness": ClearOrNot.NOT_CLEAR,
            "missing_fields": {"全部信息": "需要重新描述完整的数据需求"}
        }


    parsed_require = extracted_json["parsed_require"]

    # 定义字段的中文说明
    field_descriptions = {
        "data_range": "数据范围（需要哪个时间段的数据）",
        "statistical": "统计主体（要统计什么对象）",
        "cycle": "数据周期（年/月/日/小时/周）",
        "extract_methord": "抽取方式（增量/全量/新增）",
        "effectiveness": "时效性要求（多久需要更新一次）",
        "applications": "应用场景（这个数据用来做什么）",
        "sensitive_type": "是否涉及敏感信息（true/false）",
        "sensitive_details": "具体的敏感信息类型（姓名、证件号、手机号、住址、IMEI等）",
        "fields_info": "具体需要的数据字段信息"
    }

    # 必填字段列表（除了非必填字段）
    required_fields = [
        "data_range", "statistical", "cycle", "extract_methord",
        "effectiveness", "applications"
    ]

    missing_fields = {}

    # 检查必填字段是否都有明确的值
    for field in required_fields:
        if field not in parsed_require:
            missing_fields[field] = field_descriptions[field]
        else:
            value = parsed_require[field]
            if not value or value == "未明确" or (isinstance(value, str) and value.strip() == ""):
                missing_fields[field] = field_descriptions[field]

    # 检查fields_info是否有内容
    fields_info = parsed_require.get("fields_info", [])
    if not fields_info or len(fields_info) == 0:
        missing_fields["fields_info"] = field_descriptions["fields_info"]
    else:
        # 检查字段信息是否完整
        incomplete_fields = []
        for i, field_info in enumerate(fields_info):
            if not field_info.get("original_field") or field_info.get("original_field") == "未明确":
                incomplete_fields.append(f"字段{i+1}")

        if incomplete_fields:
            missing_fields["fields_info"] = f"需要明确以下字段的具体名称：{', '.join(incomplete_fields)}"

    clearness = ClearOrNot.CLEAR if not missing_fields else ClearOrNot.NOT_CLEAR

    return {
        "clearness": clearness,
        "missing_fields": missing_fields
    }


##目前没有调用，如果需要再次闻讯，可调用这个函数
def require_clarify(clarify_input: str) -> Dict[str, Any]:
    """
    处理用户澄清输入，更新需求信息
    Args:
        clarify_input: 用户澄清时输入的内容
    Returns:
        Dict: 包含更新后的需求信息
    """
    # 重新分析澄清后的输入
    return require_clear_or_not(clarify_input)

def update_session_state_with_clearness_result(state: SessionState, result: Dict[str, Any]) -> SessionState:
    """
    使用需求明确性分析结果更新SessionState

    Args:
        state: 当前的会话状态
        result: require_clear_or_not函数的返回结果

    Returns:
        SessionState: 更新后的状态
    """

    # 更新需求明确性状态，clearness为require_clear_or_not返回的结果，clear/not_clear
    state["require_clearness"] = result.get("clearness")

    # 更新需求JSON
    extracted_json = result.get("extracted_json")
    if extracted_json:
        state["require_json"] = extracted_json

    # 如果有错误信息，更新错误状态
    if "error" in result:
        state["error_message"] = result["error"]

    return state


def clarify_requirement_node(state: SessionState) -> SessionState:
    """澄清需求节点 - 等待用户输入澄清信息"""

    new_state = state.copy()

    # 获取用户最新输入
    user_input = next((msg.content for msg in reversed(new_state["messages"]) if isinstance(msg, HumanMessage)), None)

    if user_input is None:
        new_state["messages"] = add_messages(state["messages"], [AIMessage(content="未收到您的澄清信息，对话结束。")])
        new_state["next"] = END
        return new_state

    # 保存用户的澄清输入
    new_state["clarify_input"] = user_input
    new_state["next"] = "merge_clarification"

    return new_state


def merge_clarification_node(state: SessionState) -> SessionState:
    """合并澄清信息节点 - 将用户澄清信息与原需求合并"""

    new_state = state.copy()

    try:
        # 获取原需求和澄清信息
        original_input = next((msg.content for msg in new_state["messages"] if isinstance(msg, HumanMessage)), "")
        clarify_input = new_state.get("clarify_input", "")

        # 合并需求文本
        combined_input = f"原始需求：{original_input}\n\n补充信息：{clarify_input}"

        # 重新分析合并后的需求
        analysis_result = require_clear_or_not(combined_input)
        clearness = analysis_result["clearness"]
        extracted_json = analysis_result.get("extracted_json")
        missing_fields = analysis_result.get("missing_fields", {})

        # 更新状态
        new_state["require_clearness"] = clearness
        if extracted_json:
            new_state["require_json"] = json.dumps(extracted_json, ensure_ascii=False)

        # 根据分析结果决定下一步
        if clearness == ClearOrNot.CLEAR:
            new_state["messages"] = add_messages(state["messages"], [AIMessage(content="感谢您的补充信息，现在需求已经很完整了！")])

            new_state["next"] = END
        else:
            # 继续澄清
            clarification_question = _generate_clarification_question(missing_fields)
            new_state["messages"] = add_messages(state["messages"], [AIMessage(content=f"感谢您的补充！{clarification_question}")])
            new_state["missing_fields"] = missing_fields
            new_state["next"] = "clarify_requirement"

    except Exception as e:
        print(f"合并澄清信息出错: {e}")
        new_state["messages"] = add_messages(state["messages"], [AIMessage(content="处理澄清信息时出现错误，对话结束。")])
        new_state["next"] = END

    return new_state


def _generate_clarification_question(missing_fields: Dict[str, str]) -> str:
    """生成澄清问题"""

    if not missing_fields:
        return "您的需求描述已经很完整了。"

    question = "还需要您补充以下信息：\n\n"

    for i, (field, description) in enumerate(missing_fields.items(), 1):
        question += f"{i}. {description}\n"

    question += "\n请您逐一回答这些问题，我将为您提供更精准的数据方案。"

    return question
